﻿using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;

namespace CommonEngine
{
    /// <summary>
    /// Json序列化和反序列化辅助类 
    /// </summary>
    public static class JsonHelper
    {
        #region---将对象序列化为JSON格式---

        public static string SerializeObjectToJson(object o)
        {
            if (o == null)
                return null;

            return JsonConvert.SerializeObject(o);
        }

        public static string SerializeToJson(object o)
        {
            if (o == null)
                return null;

            IsoDateTimeConverter timeFormat = new IsoDateTimeConverter();
            timeFormat.DateTimeFormat = "yyyy-MM-dd HH:mm:ss";
            return JsonConvert.SerializeObject(o, new GuidConverter(), new DecimalConverter(), timeFormat);
        }

        public static string SerializeByConverter(object obj, params JsonConverter[] converters)
        {
            return JsonConvert.SerializeObject(obj, converters);
        }

        #endregion

        /// <summary>
        /// Newtonsoft.Json序列化（忽略循环引用，忽略Null值的属性）
        /// </summary>
        public static string SerializeObject(this object obj)
        {
            return JsonConvert.SerializeObject(obj, Formatting.Indented, new JsonSerializerSettings
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
                NullValueHandling = NullValueHandling.Ignore
            });
        }
        public static string SerializeObjectNoRN(this object obj)
        {
            string Json = JsonConvert.SerializeObject(obj, Formatting.Indented, new JsonSerializerSettings
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
                NullValueHandling = NullValueHandling.Ignore
            });

            Json = Json.Replace("\r\n", "");
            //Json = Json.Replace(" ", "");
            return Json;
        }

        /// <summary>
        /// Newtonsoft.Json反序列化（忽略循环引用）
        /// </summary>
        public static T DeserializeObject<T>(this string data)
        {
            return JsonConvert.DeserializeObject<T>(data, new JsonSerializerSettings
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore
            });
        }

        #region---将JSON反序列化为对象---

        public static object DeserializeJsonToObject(string json)
        {
            if (string.IsNullOrEmpty(json))
                return null;

            return JsonConvert.DeserializeObject(json);
        }

        /// <summary>
        /// 解析JSON字符串生成对象实体
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="json">json字符串(eg.{"ID":"112","Name":"TestData"})</param>
        /// <returns>对象实体</returns>
        public static T DeserializeJsonToObject<T>(string json) where T : class
        {
            if (string.IsNullOrEmpty(json))
                return null;

            try
            {
                JsonSerializer serializer = new JsonSerializer();
                StringReader sr = new StringReader(json);
                object o = serializer.Deserialize(new JsonTextReader(sr), typeof(T));
                T t = o as T;
                return t;
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 解析JSON数组生成对象实体集合
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="json">json数组字符串(eg.[{"ID":"112","Name":"石子儿"}])</param>
        /// <returns>对象实体集合</returns>
        public static List<T> DeserializeJsonToList<T>(string json) where T : class
        {
            if (string.IsNullOrEmpty(json))
                return null;

            try
            {
                JsonSerializer serializer = new JsonSerializer();
                StringReader sr = new StringReader(json);
                object o = serializer.Deserialize(new JsonTextReader(sr), typeof(List<T>));
                List<T> list = o as List<T>;
                return list;
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 反序列化JSON到给定的匿名对象.
        /// </summary>
        /// <typeparam name="T">匿名对象类型</typeparam>
        /// <param name="json">json字符串</param>
        /// <param name="anonymousTypeObject">匿名对象</param>
        /// <returns>匿名对象</returns>
        public static T DeserializeAnonymousType<T>(string json, T anonymousTypeObject)
        {
            if (string.IsNullOrEmpty(json))
                return default(T);

            T t = JsonConvert.DeserializeAnonymousType(json, anonymousTypeObject);
            return t;
        }

        #endregion

        /// <summary>
        /// 算法打包
        /// </summary>
        public static string JsonSerializerObject(object input)
        {
            StringBuilder tmp = new StringBuilder();
            JsonSerializer jsonSerializer = new JsonSerializer();
            using (StringWriter writer = new StringWriter(tmp))
            using (JsonWriter jsonWriter = new JsonTextWriter(writer))
            {
                jsonSerializer.Serialize(writer, input);
            }

            return tmp.ToString();
        }

        //解决JSON转换空GUID问题
        public class GuidConverter : JsonConverter
        {
            public override bool CanConvert(Type objectType)
            {
                return objectType.IsAssignableFrom(typeof(Guid));
            }

            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                Guid result = Guid.Empty;
                if (reader.Value == null)
                    return result;

                Guid.TryParse(reader.Value.ToString(), out result);
                return result;
            }

            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                serializer.Serialize(writer, value);
            }
        }

        public class DecimalConverter : JsonConverter
        {
            public override bool CanConvert(Type objectType)
            {
                return objectType.IsAssignableFrom(typeof(decimal));
            }

            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                decimal result = 0;
                if (reader.Value == null)
                    return result;

                decimal.TryParse(reader.Value.ToString(), out result);
                return result;
            }

            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                serializer.Serialize(writer, value);
            }
        }

        #region---Json操作---

        public static object ToJson(this string Json)
        {
            return Json.IsEmpty() ? null : JsonConvert.DeserializeObject(Json);
        }
        public static string ToJson(this object obj)
        {
            var timeConverter = new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" };
            return JsonConvert.SerializeObject(obj, timeConverter);
        }
        public static string ToJson(this object obj, string datetimeformats)
        {
            var timeConverter = new IsoDateTimeConverter { DateTimeFormat = datetimeformats };
            return JsonConvert.SerializeObject(obj, timeConverter);
        }
        public static T ToObject<T>(this string Json)
        {
            return Json.IsEmpty() ? default(T) : JsonConvert.DeserializeObject<T>(Json);
        }
        public static List<T> ToList<T>(this string Json)
        {
            return Json.IsEmpty() ? null : JsonConvert.DeserializeObject<List<T>>(Json);
        }
        public static DataTable ToTable(this string Json)
        {
            return Json.IsEmpty() ? null : JsonConvert.DeserializeObject<DataTable>(Json);
        }
        public static JObject ToJObject(this string Json)
        {
            return Json.IsEmpty() ? JObject.Parse("{}") : JObject.Parse(Json.Replace("&nbsp;", ""));
        }

        #endregion 
    }
}
